# urllib提供了一系列用于操作URL的功能。
import urllib
# urllib的request模块可以非常方便地抓取URL内容，也就是发送一个GET请求到指定的页面，然后返回HTTP的响应：
# 例如，对豆瓣的一个URLhttps://api.douban.com/v2/book/2129650进行抓取，并返回响应：
from urllib import request
with request.urlopen('http://word.kekenet.com/index.php?do=levelbegin&cid=533') as f:
    data = f.read()
    print('Status:', f.status, f.reason)
    for k, v in f.getheaders():
        print('%s: %s' % (k, v))
    print('Data:', data.decode('gbk'))

# 如果我们要想模拟浏览器发送GET请求，就需要使用Request对象，通过往Request对象添加HTTP头，我们就可以把请求伪装成浏览器。例如，模拟iPhone 6去请求豆瓣首页：
from urllib import request
req = request.Request('http://sspai.com/')
req.add_header('User-Agent', 'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25')
with request.urlopen(req) as f:
    print('Status:', f.status, f.reason)
    for k, v in f.getheaders():
        print('%s: %s' % (k, v))
    print('Data:', f.read().decode('utf-8'))

# 如果要以POST发送一个请求，只需要把参数data以bytes形式传入。
from urllib import request, parse
print('Login to weibo.cn...')
email = input('Email: ')
passwd = input('Password: ')
login_data = parse.urlencode([
    ('username', email),
    ('password', passwd),
    ('entry', 'mweibo'),
    ('client_id', ''),
    ('savestate', '1'),
    ('ec', ''),
    ('pagerefer', 'https://www.oschina.net/action/user/hash_login?from=mweibo')
])
req = request.Request('https://www.oschina.net/action/user/hash_login?from=')
req.add_header('Origin', 'https://www.oschina.net')
req.add_header('User-Agent', 'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25')
req.add_header('referer', 'https://www.oschina.net/home/login?goto_page=https%3A%2F%2Fwww.oschina.net%2Fnews')
with request.urlopen(req, data=login_data.encode('utf-8')) as f:
    print('Status:', f.status, f.reason)
    for k, v in f.getheaders():
        print('%s: %s' % (k, v))
    print('Data:', f.read().decode('utf-8'))

# 如果还需要更复杂的控制，比如通过一个Proxy去访问网站，我们需要利用ProxyHandler来处理，示例代码如下：
from urllib import request
# ProxyHandler 是 urllib.request 模块中的一个类，用于设置代理服务器。这里传入一个字典，其中键 http 表示要使用的协议，值 http://www.example.com:3128/ 是代理服务器的地址和端口。通过这个对象，后续的请求将通过该代理服务器进行转发。
proxy_handler = urllib.request.ProxyHandler({'http': 'http://www.example.com:3128/'})
# 这个对象用于处理代理服务器的基本认证。如果代理服务器需要用户名和密码进行认证，这个对象将用于后续的认证操作。
proxy_auth_handler = urllib.request.ProxyBasicAuthHandler()
# 调用 add_password 方法向 proxy_auth_handler 对象添加认证信息。realm 是认证的领域，host 是代理服务器的主机名，username 和 password 是用于登录代理服务器的用户名和密码。
proxy_auth_handler.add_password('realm', 'host', 'username', 'password')
# 使用 build_opener 函数创建了一个 OpenerDirector 对象 opener。这个对象将结合 proxy_handler 和 proxy_auth_handler，可以处理通过代理服务器发送请求以及进行认证的操作。build_opener 函数允许你组合多个处理程序（如 ProxyHandler 和 ProxyBasicAuthHandler），这样当使用这个 opener 打开一个 URL 时，这些处理程序将按顺序执行相应的操作。
opener = urllib.request.build_opener(proxy_handler, proxy_auth_handler)
# 使用 opener 对象的 open 方法打开一个 URL http://www.example.com/login.html。open 方法会返回一个类似于文件的对象 f，你可以对其进行读取等操作。
# with 语句确保在使用完 f 后自动关闭连接。
with opener.open('http://www.example.com/login.html') as f:
    print(f.read().decode('utf-8'))
